package operations;

import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.Collections;
import javax.swing.AbstractAction;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import controller.EditorController;
public class AutoComplete {
	int oldpos=0;
	
	private final java.util.List<String> words;
	private static java.util.List<String> match;
	boolean insertUpdate;
	public CommitTab commitTab;
	public CommitAction commitAction;
	static int pd,spw,wordfind=0,matchWord = 0;
	private static enum Mode { INSERT, COMPLETION };
    
    private Mode mode = Mode.INSERT;
	public AutoComplete()
	{
		words = new ArrayList<String>();
		match = new ArrayList<String>();
		commitTab=new CommitTab();
		commitAction=new CommitAction();
		insertUpdate=false;
	}
	public void insertUpdate(DocumentEvent ev,String content) {
		//System.out.println("111");
		//EditorController.text.replaceSelection("");
		
		 if (ev.getLength() != 1) {
			 insertUpdate=true;
			// System.out.println(content);
			
			 return;
			 
			
		}
		 
		int pos = ev.getOffset();
		
		//   String content = null;

		// Find word start
		int w;
		for (w = pos; w >= 0; w--) {
			if (! Character.isLetter(content.charAt(w))) {
				break;
			}
		}
		
		if (! Character.isLetter(content.charAt(pos))) {
			if(pos>oldpos){
				String prefix1 = content.substring(oldpos,pos);
				if(prefix1.length()>2){
					addword(prefix1.toLowerCase());
					}	
				}
			oldpos=pos+1;
			wordfind=0;
			
			 
		}

		
		else{
		String prefix = content.substring(w + 1).toLowerCase();
		if(prefix.length()<2){
			wordfind=0;
			return;
			}
		int n = Collections.binarySearch(words, prefix);
		if (n < 0 && -n <= words.size()) {
			match.clear();
			spw=w;
	    	pd=pos;
			//Matching characters from list
	    	wordfind=1;
	    	
			int searchListLength = words.size();
			for (int i = 0; i < searchListLength; i++) {
				if (words.get(i).startsWith(prefix)) {
					match.add(words.get(i));
					
				}
			}
			if(!match.isEmpty()){
			String completion = match.get(match.size()-1).substring(pos - w);
			SwingUtilities.invokeLater(new CompletionTask(completion, pos + 1));
         	matchWord =match.size()-1;
         	}
			
			
			
		

		} else {
			// Nothing found
			mode = Mode.INSERT;
		}}
	}

	public void addword(String word)
	{
		boolean wordFound=false;
		for (int i = 0; i < words.size(); i++) {
			if (words.get(i).equalsIgnoreCase(word)) {
				wordFound=true;
				
			}
		}
		if (wordFound==false) {
			words.add(word);
		}
		}
	
	public class CommitTab extends AbstractAction {
		//For changing word on tab
	       public void actionPerformed(ActionEvent ev) {
	    	   if(insertUpdate==false) return;
	    	   if(wordfind==1){
	    		 if(!match.isEmpty()) {
	    		 
	    		 try{  
	    	 
	    	   matchWord--;
	    	   if(matchWord<0){
	    		   matchWord=match.size()-1;
	    	   }
	    	  
	    	   EditorController.text.replaceSelection("");
	    	   String completion = match.get(matchWord).substring(pd - spw);
	    	   SwingUtilities.invokeLater(new CompletionTask(completion, pd + 1));
	    	  }catch(Exception e){
	    		  System.out.println(e.getStackTrace());}
	       }
	       }
	       }
	   }
	 public class CommitAction extends AbstractAction {
			//For Completing the word on enter
		        public void actionPerformed(ActionEvent ev) {
		            if (mode == Mode.COMPLETION) {
		                int pos = EditorController.text.getSelectionEnd();
		                EditorController.text.insert(" ", pos);
		                EditorController.text.setCaretPosition(pos + 1);
		                mode = Mode.INSERT;
		            } else {
		            	EditorController.text.replaceSelection("\n");
		            }
		        }
		    }
	private class CompletionTask implements Runnable {
		String completion;
		int position;

		CompletionTask(String completion, int position) {
			this.completion = completion;
			this.position = position;
		}

		public void run() {
			EditorController.text.insert(completion, position);
			EditorController.text.setCaretPosition(position + completion.length());
			EditorController.text.moveCaretPosition(position);
			mode = Mode.COMPLETION;
		}
	}


}
